package com.thirtydays.frame.util

import com.alibaba.sdk.android.oss.ClientConfiguration
import com.alibaba.sdk.android.oss.ClientException
import com.alibaba.sdk.android.oss.OSSClient
import com.alibaba.sdk.android.oss.ServiceException
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider
import com.alibaba.sdk.android.oss.model.PutObjectRequest
import com.alibaba.sdk.android.oss.model.PutObjectResult
import com.blankj.utilcode.util.LogUtils
import com.thirtydays.frame.base.BaseApp
import java.util.*

/**
 * @author 小垚
 * @创建时间： 2020/12/2
 * @描述：OSS工具类
 **/
data class Upload(
    var accessKeyId: String = "STS.NUWiKxrfC5NheTZxG8pXeL4h7",
    var securityToken: String = "CAIS9wF1q6Ft5B2yfSjIr5biIvHMn7ligoyDZ3LrnEdtfNdJo/HD1Tz2IHFJdHhrBusXtvs+nG9Y7PYalq9/QoBeQkqcjyiVUhoRo22beIPkl5Gfz95t0e+IewW6Dxr8w7WhAYHQR8/cffGAck3NkjQJr5LxaTSlWS7OU/TL8+kFCO4aRQ6ldzFLKc5LLw950q8gOGDWKOymP2yB4AOSLjIx5VEi2DMusvrunpDBskqDtjCglL9J/baWC4O/csxhMK14V9qIx+FsfsLDqnUBtkgbr/gt3fQbqG+Y7ovNW0Mr+RKCPq/T6cYqLhQ8e7A+HKdIvH03HEeVKw64GoABJbPHlMnP89KnUOL/fsme5yGTqvIUkoeb1G+6OZgpYbyhmK8SMFeM7GyJ6MIH5WuxFeu5JfiUi4fhpkXstASbc/SJ/CjRKEKQyo0iftBIzGyN3byYb9iFxviA1YI7CuYmn9neVveObM3CgpPPn3cMp4yfupODHf7J8ZavLy220Vo=",
    var accessKeySecret: String = "FfRruuK4qXjNUgWb44D8hCvQDvm5X4GrG7PNzfAFnAq5",
    var endPoint: String = "oss-cn-beijing.aliyuncs.com",
    var cdn: String = "https://cdn.jinaokj.cn",
    var bucketName: String = "smarklothing",
)

data class ResultBean(
    var isSuccess: Boolean = true,
    var message: String = "",
    var url: String = ""
)


class OSSUtils() {
    companion object {
        val INSTANCE: OSSUtils by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            OSSUtils()
        }
    }

    private lateinit var ossClient: OSSClient
    private lateinit var mUpload: Upload

    private fun initOSS(upload: Upload) {
        mUpload = upload

        // 在移动端建议使用STS的方式初始化OSSClient。
        val credentialProvider = OSSStsTokenCredentialProvider(
            upload.accessKeyId,
            upload.accessKeySecret,
            upload.securityToken
        )
        val conf = ClientConfiguration()
        conf.connectionTimeout = 15 * 1000 // 连接超时，默认15秒。
        conf.socketTimeout = 15 * 1000 // socket超时，默认15秒。
        conf.maxConcurrentRequest = 5 // 最大并发请求书，默认5个。
        conf.maxErrorRetry = 2 // 失败后最大重试次数，默认2次。
        ossClient = OSSClient(BaseApp.sInstance, upload.endPoint, credentialProvider, conf)
    }

    fun uploadFile(
        upload: Upload,
        filePath: String,
        fileName: String,
        progressCallback: OSSProgressCallback<PutObjectRequest>?
    ): ResultBean {
        if (!this::mUpload.isInitialized) {
            initOSS(upload)
        }
        // 构造上传请求。
        val putObjectRequest = PutObjectRequest(mUpload.bucketName, fileName, filePath)

        progressCallback?.let {
            putObjectRequest.progressCallback = it
        }

        var bean = ResultBean()

        val asyncPutObject = ossClient.asyncPutObject(
            putObjectRequest,
            object : OSSCompletedCallback<PutObjectRequest, PutObjectResult> {
                override fun onSuccess(request: PutObjectRequest?, result: PutObjectResult?) {
                    bean.url = getUrl(upload.bucketName, fileName).split("\\?".toRegex()).toTypedArray()[0]
                    bean.isSuccess = true
                }

                override fun onFailure(
                    request: PutObjectRequest?,
                    clientException: ClientException?,
                    serviceException: ServiceException?
                ) {
                    LogUtils.e(serviceException?.message)
                    bean.message = "${serviceException?.message}"
                    bean.isSuccess = false
                }

            })
        asyncPutObject.waitUntilFinished()
        return bean
    }


    /**
     * 获得url链接
     */
    fun getUrl(bucketName: String, key: String): String {
        // 设置URL过期时间为10年  3600l* 1000*24*365*10
        val expiration = Date(Date().time + 3600L * 1000 * 24 * 365 * 10)
        // 生成URL
        var url = ""
        try {
            url = ossClient.presignConstrainedObjectURL(bucketName, key, expiration.time)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return url
    }


}